///
/// @file Module.cpp
/// @brief  符号表-模块类
/// @author zenglj (zenglj@live.com)
/// @version 1.0
/// @date 2024-09-29
///
/// @copyright Copyright (c) 2024
///
/// @par 修改日志:
/// <table>
/// <tr><th>Date       <th>Version <th>Author  <th>Description
/// <tr><td>2024-09-29 <td>1.0     <td>zenglj  <td>新建
/// </table>
///
#include "Module.h"

#include "ScopeStack.h"
#include "Common.h"
#include "VoidType.h"
#include "PointerType.h"
#include "ConstFloat.h"
#include "ConstInt.h"
#include "PointerType.h" // 新增：用于数组参数
#include "CharType.h"
#include "Analysis/LivenessAnalysis.h" // 新增
#include "Analysis/LivenessCFGAnalysis.h"
#include <cstdio>
#include <iostream>

Module::Module(std::string _name) : name(_name)
{
    // 创建作用域栈
    scopeStack = new ScopeStack();

    // 确保全局变量作用域入栈，这样全局变量才可以加入
    scopeStack->enterScope();

    // 加入内置函数putint
    (void) newFunction("putint", VoidType::getType(), {new FormalParam{IntegerType::getTypeInt(), ""}}, true);
    (void) newFunction("getint", IntegerType::getTypeInt(), {}, true);

    // 新增：添加std.c中的其他内置函数
    // int getch()
    (void) newFunction("getch", IntegerType::getTypeInt(), {}, true);

    // int getarray(int a[]) - 数组参数转换为指针
    (void) newFunction("getarray",
                       IntegerType::getTypeInt(),
                       {new FormalParam{new PointerType(IntegerType::getTypeInt()), ""}},
                       true);

    // void putch(int c)
    (void) newFunction("putch", VoidType::getType(), {new FormalParam{IntegerType::getTypeInt(), ""}}, true);

    // void putarray(int n, int *d)
    (void) newFunction("putarray",
                       VoidType::getType(),
                       {new FormalParam{IntegerType::getTypeInt(), ""},
                        new FormalParam{new PointerType(IntegerType::getTypeInt()), ""}},
                       true);

    // float getfloat()
    (void) newFunction("getfloat", FloatType::getTypeFloat(), {}, true);

    // int getfarray(float a[])
    (void) newFunction("getfarray",
                       IntegerType::getTypeInt(),
                       {new FormalParam{new PointerType(FloatType::getTypeFloat()), ""}},
                       true);

    // void putfloat(float a)
    (void) newFunction("putfloat", VoidType::getType(), {new FormalParam{FloatType::getTypeFloat(), ""}}, true);

    // void putfarray(int n, float a[])
    (void) newFunction("putfarray",
                       VoidType::getType(),
                       {new FormalParam{IntegerType::getTypeInt(), ""},
                        new FormalParam{new PointerType(FloatType::getTypeFloat()), ""}},
                       true);

    // void putf(char a[], ...) - 可变参数函数，这里简化为char*参数
    (void) newFunction("putf", VoidType::getType(), {new FormalParam{new PointerType(CharType::getType()), ""}}, true);

    // 时间相关函数（在OPT_TEST模式下）
    // void _sysy_starttime(int lineno)
    (void) newFunction("_sysy_starttime", VoidType::getType(), {new FormalParam{IntegerType::getTypeInt(), ""}}, true);

    // void _sysy_stoptime(int lineno)
    (void) newFunction("_sysy_stoptime", VoidType::getType(), {new FormalParam{IntegerType::getTypeInt(), ""}}, true);
}

/// @brief 进入作用域，如进入函数体块、语句块等
void Module::enterScope()
{
    scopeStack->enterScope();
}

/// @brief 退出作用域，如退出函数体块、语句块等
void Module::leaveScope()
{
    scopeStack->leaveScope();
}

///
/// @brief 在遍历抽象语法树的过程中，获取当前正在处理的函数。在函数外处理时返回空指针。
/// @return Function* 当前处理的函数对象
///
Function * Module::getCurrentFunction()
{
    return currentFunc;
}

///
/// @brief 设置当前正在处理的函数指针。函数外设置空指针
/// @param current 函数对象
///
void Module::setCurrentFunction(Function * current)
{
    currentFunc = current;
}

/// @brief 新建函数并放到函数列表中
/// @param name 函数名
/// @param returnType 返回值类型
/// @param params 形参列表
/// @param builtin 是否内置函数
/// @return 新建的函数对象实例
Function * Module::newFunction(std::string name, Type * returnType, std::vector<FormalParam *> params, bool builtin)
{
    // 先根据函数名查找函数，若找到则出错
    Function * tempFunc = findFunction(name);
    if (tempFunc) {
        // 函数已存在
        return nullptr;
    }

    // 创建函数类型
    std::vector<Type *> paramTypes;
    for (auto * p: params) {
        paramTypes.push_back(p->getType());
    }
    FunctionType * funcType = new FunctionType(returnType, paramTypes);

    // 新建函数对象
    tempFunc = new Function(name, funcType, builtin);
    tempFunc->getParams() = params;
    insertFunctionDirectly(tempFunc);
    return tempFunc;
}

/// @brief 根据函数名查找函数信息
/// @param name 函数名
/// @return 函数信息
Function * Module::findFunction(std::string name)
{
    // 根据名字查找
    auto pIter = funcMap.find(name);
    if (pIter != funcMap.end()) {
        // 查找到
        return pIter->second;
    }

    return nullptr;
}

///
/// @brief 直接向函数的符号表中加入函数。需外部检查函数的存在性
/// @param func 要加入的函数
///
void Module::insertFunctionDirectly(Function * func)
{
    funcMap.insert({func->getName(), func});
    funcVector.emplace_back(func);
}

/// @brief Value直接插入到符号表中的全局变量中
/// @param name Value的名称
/// @param val Value信息
void Module::insertGlobalValueDirectly(GlobalVariable * val)
{
    globalVariableMap.emplace(val->getName(), val);
    globalVariableVector.push_back(val);
}

/// @brief Value直接插入到符号表中的全局变量中
/// @param name Value的名称
/// @param val Value信息
void Module::insertConstIntDirectly(ConstInt * val)
{
    constIntMap.emplace(val->getVal(), val);
}

/// @brief 新建一个整型数值的Value，并加入到符号表，用于后续释放空间
/// @param intVal 整数值
/// @return 常量Value
ConstInt * Module::newConstInt(int32_t intVal)
{
    // 查找整数字符串
    ConstInt * val = findConstInt(intVal);
    if (!val) {

        // 不存在，则创建整数常量Value
        val = new ConstInt(intVal);

        insertConstIntDirectly(val);
    }

    return val;
}
// 查找浮点常量
ConstFloat * Module::findConstFloat(float v)
{
    auto it = constFloatMap.find(v);
    return it != constFloatMap.end() ? it->second : nullptr;
}

// 直接插入浮点常量
void Module::insertConstFloatDirectly(ConstFloat * val)
{
    constFloatMap.emplace(val->getFloatVal(), val); // 使用getFloatVal()而不是getVal()
}

// 新建浮点常量并加入符号表
ConstFloat * Module::newConstFloat(float v)
{
    ConstFloat * c = findConstFloat(v);
    if (!c) {
        c = new ConstFloat(v);
        insertConstFloatDirectly(c);
    }
    return c;
}
ConstantArray * Module::newConstantArray(PointerType * type, const std::vector<Value *> & values)
{
    // 验证类型和值数量匹配
    if (values.size() != static_cast<size_t>(type->getSize() / type->getRootType()->getSize())) {
        return nullptr;
    }

    // 验证所有值的类型匹配
    const Type * elemType = type->getRootType();
    for (Value * val: values) {
        if (!val->getType()->equals(elemType)) {
            return nullptr;
        }
    }

    return new ConstantArray(type, values);
}

/// @brief 根据整数值获取当前符号
/// \param name 变量名
/// \return 变量对应的值
ConstInt * Module::findConstInt(int32_t val)
{
    ConstInt * temp = nullptr;

    auto pIter = constIntMap.find(val);
    if (pIter != constIntMap.end()) {
        // 查找到
        temp = pIter->second;
    }

    return temp;
}

/// @brief 在当前的作用域中查找，若没有查找到则创建局部变量或者全局变量。请注意不能创建临时变量
/// ! 该函数只有在AST遍历生成线性IR中使用，其它地方不能使用
/// @param type 变量类型
/// @param name 变量ID 局部变量时可以为空，目的为了SSA时创建临时的局部变量，
/// @param allowShadowing 是否允许遮蔽外层变量（默认true）
/// @return nullptr则说明变量已存在，否则为新建的变量
///
Value * Module::newVarValue(Type * type, std::string name, bool allowShadowing)
{
    Value * retVal;
    std::string varName;

    // 若变量名有效，检查当前作用域中是否存在变量
    if (!name.empty()) {
        Value * tempValue = scopeStack->findCurrentScope(name);
        if (tempValue && !allowShadowing) {
            // 变量存在且不允许遮蔽，语义错误
            minic_log(LOG_ERROR, "变量(%s)已经存在", name.c_str());
            return nullptr;
        }
        // 如果允许遮蔽，即使当前作用域存在同名变量也可以创建新变量
    } else if (!currentFunc) {
        // 全局变量要求name不能为空串，必须有效
        minic_log(LOG_ERROR, "变量名为空");
        return nullptr;
    }

    if (currentFunc) {
        // 获取变量作用域的层级
        int32_t scope_level;
        if (name.empty()) {
            scope_level = 1;
        } else {
            scope_level = scopeStack->getCurrentScopeLevel();
        }

        retVal = currentFunc->newLocalVarValue(type, name, scope_level);
    } else {
        retVal = newGlobalVariable(type, name);
    }

    // 增加到当前作用域中（即使存在同名变量也会覆盖映射）
    scopeStack->insertValue(retVal);

    return retVal;
}

// 重载版本保持向后兼容
Value * Module::newVarValue(Type * type, std::string name)
{
    return newVarValue(type, name, true); // 默认允许遮蔽
}

/// @brief 查找变量，会根据作用域栈进行逐级查找。
/// ! 该函数只有在AST遍历生成线性IR中使用，其它地方不能使用
///
/// @param name 变量ID
/// @return 指针有效则找到，空指针未找到
Value * Module::findVarValue(std::string name)
{
    // 在作用域栈中查找变量
    Value * val = scopeStack->findAllScope(name);
    if (val) {
        return val;
    }

    // 在常量表中查找
    auto it = constTable.find(name);
    if (it != constTable.end()) {
        return it->second;
    }

    // 查找函数（函数名可以作为函数指针使用）
    Function * func = findFunction(name);
    if (func) {
        return func;
    }

    return nullptr;
}
// Value * Module::findVarValue(std::string name)
// {
//     std::cout << "开始查找变量: " << name << std::endl;

//     // 逐层级作用域查找
//     std::cout << "正在作用域栈中查找变量..." << std::endl;
//     Value * tempValue = scopeStack->findAllScope(name);
//     if (tempValue) {
//         std::cout << "在作用域栈中找到变量: " << name << ", 类型为: ";
//         if (tempValue->getType()) {
//             std::cout << tempValue->getType()->toString() << std::endl;
//         } else {
//             std::cout << "未知类型" << std::endl;
//         }
//     } else {
//         std::cout << "在作用域栈中未找到变量: " << name << std::endl;
//     }

//     // 如果在作用域中没找到，尝试从常量表中查找
//     if (!tempValue) {
//         std::cout << "正在常量表中查找变量..." << std::endl;
//         auto it = constTable.find(name);
//         if (it != constTable.end()) {
//             std::cout << "在常量表中找到变量: " << name << ", 类型为: ";
//             if (it->second->getType()) {
//                 std::cout << it->second->getType()->toString() << std::endl;
//             } else {
//                 std::cout << "未知类型" << std::endl;
//             }
//             return it->second;
//         } else {
//             std::cout << "在常量表中未找到变量: " << name << std::endl;
//         }
//     }

//     return tempValue;
// }

///
/// @brief 新建全局变量，要求name必须有效，并且加入到全局符号表中。不检查是否现有的符号表中是否存在。
/// @param type 类型
/// @param name 名字
/// @param initializer 初始化值
/// @return Value* 全局变量
GlobalVariable * Module::newGlobalVariable(Type * type, std::string name, Constant * initializer)
{
    // 创建全局变量对象
    GlobalVariable * val = new GlobalVariable(type, name, initializer);

    // 如果有初始化值，设置初始化值
    if (initializer) {
        val->setInitializer(initializer);
    }

    // 插入到全局变量符号表
    insertGlobalValueDirectly(val);

    // 插入到全局作用域栈，保证findVarValue能查到
    if (scopeStack) {
        // 只在全局作用域插入
        scopeStack->valueStack.front()[name] = val;
    }

    return val;
}

/// @brief 新建全局变量（无初始化值）
/// @param type 类型
/// @param name 名字
/// @return Value* 全局变量
GlobalVariable * Module::newGlobalVariable(Type * type, std::string name)
{
    return newGlobalVariable(type, name, nullptr);
}

/// @brief 根据变量名获取当前符号(只管理全局变量和常量)
/// @param name 变量名或者常量名
/// @param create 变量查找不到时若为true则自动创建变量型Value，否则不创建
/// @return 变量对应的值
GlobalVariable * Module::findGlobalVariable(std::string name)
{
    GlobalVariable * temp = nullptr;

    auto pIter = globalVariableMap.find(name);
    if (pIter != globalVariableMap.end()) {
        // 查找到
        temp = pIter->second;
    }

    return temp;
}

/// @brief 清理注册的所有Value资源
void Module::Delete()
{
    // 清除所有的函数
    for (auto func: funcVector) {
        delete func;
    }

    // 清理全局变量
    for (auto var: globalVariableVector) {
        delete var;
    }

    // 相关列表清空
    globalVariableMap.clear();
    globalVariableVector.clear();

    funcMap.clear();
    funcVector.clear();
}

///
/// @brief 对IR指令中没有名字的全部命名
///
void Module::renameIR()
{
    // 全局变量目前都有名字，目前不存在没有名字的变量，因此
    // 对于全局变量的线性IR名称，只是在原来的名称前追加@即可

    // 遍历所有的函数，含局部变量名、形参、Label名、指令变量重命名
    for (auto func: funcVector) {
        func->renameIR();
    }
}

/// @brief 文本输出线性IR指令
/// @param filePath 输出文件路径
void Module::outputIR(const std::string & filePath)
{
    // 这里使用C的文件操作，也可以使用C++的文件操作

    FILE * fp = fopen(filePath.c_str(), "w");
    if (nullptr == fp) {
        printf("fopen() failed\n");
        return;
    }

    // 全局变量遍历输出对应的定义指令
    for (auto var: globalVariableVector) {
        std::string str;
        var->toDefineString(str); // 输出全局变量定义，包括初始化值
        fprintf(fp, "%s\n", str.c_str());
    }

    // 新增：遍历所有函数，为内置函数输出声明
    for (auto func: funcVector) {
        if (func->isBuiltin()) {
            std::string decl_str = "declare " + func->getReturnType()->toString() + " " + func->getIRName() + "(";
            auto & params = func->getParams();
            for (size_t i = 0; i < params.size(); ++i) {
                if (i > 0) {
                    decl_str += ", ";
                }
                decl_str += params[i]->getType()->toString();
            }
            decl_str += ")\n";
            fprintf(fp, "%s", decl_str.c_str());
        }
    }

    // 遍历所有的线性IR指令，文本输出
    for (auto func: funcVector) {
        std::string instStr;
        func->toString(instStr);
        if (!instStr.empty()) {
            fprintf(fp, "%s", instStr.c_str());
        }

        // // ----------- 活跃间隔 -----------
        // LivenessAnalysis liveness;
        // liveness.analyze(func);
        // auto intervals = liveness.getLiveIntervals(func);
        // for (const auto & kv: intervals) {
        //     std::cout << kv.first << ": [" << kv.second.first << ", " << kv.second.second << "]" << std::endl;
        // }

        // // ----------- 指令级别活跃变量分析 -----------
        // // LivenessAnalysis liveness;
        // liveness.analyze(func);
        // std::cout << "==== [Linear] Liveness Analysis for function: " << func->getName() << " ====" << std::endl;
        // liveness.printLiveness(func);
        // std::cout << std::endl;

        // ----------- 块级别（CFG）活跃变量分析 -----------
        // std::vector<Instruction *> insts = func->getInterCode().getInsts();
        // std::vector<BasicBlock *> blocks;
        // buildBasicBlocks(insts, blocks);

        // LivenessCFGAnalysis livenessCFG;
        // livenessCFG.analyze(blocks);
        // std::cout << "==== [CFG] Liveness Analysis for function: " << func->getName() << " ====" << std::endl;
        // livenessCFG.printLiveness(blocks);
        // std::cout << std::endl;

        // // 可选：释放blocks内存
        // for (auto * bb: blocks)
        //     delete bb;
    }

    fclose(fp);
}

// 注册常量名到常量值
void Module::addConstValue(const std::string & name, Value * val)
{
    constTable[name] = val;
}

Type * Module::createPointerType(Type * baseType, const std::vector<int32_t> & dimensions)
{
    // 参数检查
    if (!baseType || dimensions.empty()) {
        minic_log(LOG_ERROR, "Cannot create array type: invalid parameters");
        return nullptr;
    }

    // 检查维度合法性
    for (int dim: dimensions) {
        if (dim <= 0) {
            minic_log(LOG_ERROR, "Array dimension must be positive (got %d)", dim);
            return nullptr;
        }
    }

    // 从内到外构建嵌套数组类型
    Type * currentType = baseType;
    for (auto it = dimensions.rend() - 1; it != dimensions.rbegin() - 1; --it) {
        currentType = new PointerType(currentType, true, *it);
        // 注册类型到模块（如果需要）
        // typeTable.addType(currentType);
    }

    return currentType;
}